package makovo.utils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.util.Dictionary;
import java.util.Hashtable;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;

public class FTPAccess {
	private static FTPAccess mInstance;
	private FTPClient mClient;
	private static final Object myLock = new Object();
	private Dictionary<String, String> mProperties = new Hashtable<>();

	public static FTPAccess getInstance() throws Exception {
		if (mInstance == null)
			synchronized (myLock) {
				if (mInstance == null)
					try {
						mInstance = new FTPAccess();
					} catch (IOException e) {
						throw new Exception(e.getMessage());
					}
			}

		return mInstance;
	}

	private FTPAccess() throws IOException {

		String[] par;

		String propFile = IOUtils.toString(this.getClass().getResourceAsStream("/makovo/resources/ftp.properties"));

		String props[] = propFile.split("\n");

		for (String p : props) {
			par = p.replaceFirst("\n", "").split("=");
			mProperties.put(par[0], par[1]);
		}

		propFile = null;

	}

	private String formatFile(String remoteFile) {
		String dir = mProperties.get("ftp.rootDirectory");

		if (dir.endsWith("/"))
			dir = dir + remoteFile;
		else
			dir = dir + "/" + remoteFile;
		
		return dir;
	}

	public String getServer() {
		String url = mProperties.get("ftp.server");
		if (url.contains("/public_html"))
			url = url.replace("/public_html", "");

		return url;
	}

	public synchronized boolean dirExists(String fileName) {
		boolean exists = false;

		String path = FilenameUtils.getPath(formatFile(fileName));
		path = path.substring(0, path.length() - 1);
		String rootPath = path.lastIndexOf("/") == -1 ? "/" : path.substring(0, path.lastIndexOf("/"));

		return exists;

	}

	public synchronized boolean fileExists(String fileName, boolean remove) throws NumberFormatException, SocketException,
			IOException {
		boolean exists = false;
		mClient = new FTPClient();

		mClient.connect(mProperties.get("ftp.server"), Integer.valueOf(mProperties.get("ftp.port")));
		mClient.login(mProperties.get("ftp.user"), mProperties.get("ftp.password"));
		mClient.enterLocalPassiveMode();

		String root = FilenameUtils.getPath(formatFile(fileName));
		String name = FilenameUtils.getName(fileName);

		FTPFile[] files = mClient.listFiles(root);

		if (files.length > 0) {
			for (int i = 0; i < files.length; i++) {
				if (files[i].getName().equals(name)) {
					exists = true;

					mClient.disconnect();

					if (remove)
						exists = !removeFile(fileName);

					break;
				}

			}

		}

		return exists;

	}

	public synchronized boolean removeFile(String pathName) throws NumberFormatException, SocketException, IOException {
		mClient = new FTPClient();

		mClient.connect(mProperties.get("ftp.server"), Integer.valueOf(mProperties.get("ftp.port")));
		mClient.login(mProperties.get("ftp.user"), mProperties.get("ftp.password"));
		mClient.enterLocalPassiveMode();

		String file = formatFile(pathName);

		boolean done = mClient.deleteFile(file);

		if (mClient.isConnected()) {
			mClient.logout();
			mClient.disconnect();
		}

		return done;

	}

	public synchronized String makeDir(String directory) throws NumberFormatException, SocketException, IOException {
		String dir = directory;
		mClient = new FTPClient();

		mClient.connect(mProperties.get("ftp.server"), Integer.valueOf(mProperties.get("ftp.port")));
		mClient.login(mProperties.get("ftp.user"), mProperties.get("ftp.password"));
		mClient.enterLocalPassiveMode();

		dir = formatFile(directory);
		boolean done = mClient.makeDirectory(dir);

		if (mClient.isConnected()) {
			mClient.logout();
			mClient.disconnect();
		}

		if (done)
			return dir;
		else
			return null;

	}

	public synchronized String uploadFile(byte[] localFileData, String remoteFileName) throws NumberFormatException,
			SocketException, IOException {
		mClient = new FTPClient();

		mClient.connect(mProperties.get("ftp.server"), Integer.valueOf(mProperties.get("ftp.port")));
		mClient.login(mProperties.get("ftp.user"), mProperties.get("ftp.password"));
		mClient.enterLocalPassiveMode();

		mClient.setFileType(FTP.BINARY_FILE_TYPE);

		String remote = formatFile(remoteFileName);
		InputStream is = new ByteArrayInputStream(localFileData);
		boolean done = mClient.storeFile(remote, is);

		is.close();

		if (mClient.isConnected()) {
			mClient.logout();
			mClient.disconnect();
		}

		if (done)
			return remote;
		else
			return null;

	}
	
	public synchronized boolean deleteDirectory(String pathName) throws NumberFormatException, SocketException, IOException{
		boolean ret = false;
		mClient = new FTPClient();

		mClient.connect(mProperties.get("ftp.server"), Integer.valueOf(mProperties.get("ftp.port")));
		mClient.login(mProperties.get("ftp.user"), mProperties.get("ftp.password"));
		mClient.enterLocalPassiveMode();

		String directory = formatFile(pathName);

		ret = mClient.removeDirectory(directory);

		if (mClient.isConnected()) {
			mClient.logout();
			mClient.disconnect();
		}
		
		return ret;
	}
}
